/**
  * @File    :   i2c.c
  * @Time    :   2020/04/05 15:47:01
  * @Author  :   huenrong
  */

#include "i2c.h"

/**
  * @name   i2c_write_data
  * @brief  向无寄存器地址的i2c从设备发送数据/命令
  * @param  fd: i2c从设备文件描述符
  * @param  slave_addr: 需要发送的数据/命令
  * @param  slave_addr: 需要发送的数据/命令长度
  * @retval 成功: 0
  *         失败: -1
  */
int i2c_write_data(const int fd, const uint8_t *send_data, const uint8_t send_data_len)
{
    int ret = -1;

    // 向I2C从设备发送数据/命令
    ret = write(fd, send_data, send_data_len);
    // 发送失败返回-1
    if (send_data_len != ret)
    {
        perror("i2c_write_data write error");

        return -1;
    }

    return 0;
}

/**
  * @name   i2c_read_data
  * @brief  从无寄存器地址的i2c从设备读取数据
  * @param  fd: i2c从设备文件描述符
  * @param  recv_data_len: 指定读取长度
  * @param  recv_data: 读取到的数据
  * @retval 成功: 0
  *         失败: -1
  */
int i2c_read_data(const int fd, const uint8_t recv_data_len, uint8_t *recv_data)
{
    int ret = -1;

    // 从i2c从设备读取数据
    ret = read(fd, recv_data, recv_data_len);
    // 发送失败返回-1
    if (recv_data_len != ret)
    {
        perror("i2c_read_data read error");

        return -1;
    }

    return 0;
}

#if 0
/**
  * @name   i2c_write_data_sub
  * @brief  向有寄存器的i2c从设备发送数据/命令(即写i2c从设备寄存器)
  * @param  fd: i2c从设备文件描述符
  * @param  reg_addr: i2c从设备寄存器地址
  * @param  send_data: 需要发送的数据/命令
  * @param  send_data_len: 需要发送的数据/命令长度
  * @retval 成功: 0
  *         失败: -1
  */
int i2c_write_data_sub(const int fd, const uint8_t reg_addr, const uint8_t *send_data,
                       const uint8_t send_data_len)
{
    int ret = -1;
    // i2c发送给从设备的数据
    uint8_t i2c_send_buf[257] = {0};
    // i2c发送给从设备的数据长度
    uint16_t i2c_send_buf_len = 0;

    // 写i2c从设备寄存器时, 先发送i2c从设备地址, 然后写入寄存器地址, 最后写入数据/命令
    i2c_send_buf[0] = reg_addr;
    memcpy(&i2c_send_buf[1], send_data, send_data_len);

    i2c_send_buf_len = (send_data_len + 1);

    printf("i2c send data[len = %d]: ", i2c_send_buf_len);
    for (uint8_t i = 0; i < i2c_send_buf_len; i++)
    {
        printf("0x%02X ", i2c_send_buf[i]);
    }
    printf("\n");

    // 向i2c从设备发送数据/命令
    ret = write(fd, i2c_send_buf, i2c_send_buf_len);
    // 发送失败返回-1
    if (i2c_send_buf_len != ret)
    {
        perror("i2c_write_data_sub write error");

        return -1;
    }

    return 0;
}

/**
  * @name   i2c_read_data_sub
  * @brief  从有寄存器地址的i2c从设备读取数据(即读i2c从设备寄存器)
  * @param  fd: i2c从设备文件描述符
  * @param  reg_addr: i2c从设备寄存器地址
  * @param  recv_data_len: 指定读取长度
  * @param  recv_data: 读取到的数据
  * @retval 成功: 0
  *         失败: -1
  */
int i2c_read_data_sub(const int fd, const uint8_t reg_addr, const uint8_t recv_data_len,
                      uint8_t *recv_data)
{
    int ret = -1;

    // 从i2c从设备寄存器读取数据时, 先写入要读取的i2c从设备寄存器地址, 再读取数据

    // 写i2c从设备寄存器地址
    ret = write(fd, &reg_addr, 1);
    if (1 != ret)
    {
        perror("i2c_read_data_sub write error");

        return -1;
    }

    // 读取数据
    ret = read(fd, recv_data, recv_data_len);
    if (recv_data_len != ret)
    {
        perror("i2c_read_data_sub read error");

        return -1;
    }

    printf("i2c read data[len = %d]: ", recv_data_len);
    for (uint8_t i = 0; i < recv_data_len; i++)
    {
        printf("0x%02X ", recv_data[i]);
    }
    printf("\n");

    return 0;
}
#endif
/**
  * @name   i2c_write_data_sub
  * @brief  向有寄存器的i2c从设备发送数据/命令(即写i2c从设备寄存器)
  * @param  fd: i2c从设备文件描述符
  * @param  slave_addr: i2c从设备地址
  * @param  reg_addr: i2c从设备寄存器地址
  * @param  write_data: 需要发送的数据/命令
  * @param  write_data_len: 需要发送的数据/命令长度
  * @retval 成功: 实际发送长度
  *         失败: -1
  */
int i2c_write_data_sub(const int fd, const uint8_t slave_addr, const uint8_t reg_addr,
                       const uint8_t *write_data, const uint16_t write_data_len)
{
    int ret = -1;
    struct i2c_rdwr_ioctl_data ioctl_data = {0};

    ioctl_data.nmsgs = 1; // 消息数

    ioctl_data.msgs = (struct i2c_msg *)malloc(ioctl_data.nmsgs * sizeof(struct i2c_msg));
    if (NULL == ioctl_data.msgs)
    {
        perror("i2c_write_data_sub malloc msgs error");

        return -1;
    }

    ioctl_data.msgs[0].buf = (unsigned char *)malloc((write_data_len + 1) * sizeof(char));
    if (NULL == ioctl_data.msgs[0].buf)
    {
        perror("i2c_write_data_sub malloc buf error");
        free(ioctl_data.msgs);

        return -1;
    }

    ioctl_data.msgs[0].addr = slave_addr;                             // 从器件地址
    ioctl_data.msgs[0].len = (write_data_len + 1);                    // 数据长度(buf的长度)
    ioctl_data.msgs[0].flags = 0;                                     // 操作方式(0: write; 1: read)
    ioctl_data.msgs[0].buf[0] = reg_addr;                             // 寄存器地址
    memcpy(&(ioctl_data.msgs[0].buf[1]), write_data, write_data_len); // 发送数据

    ret = ioctl(fd, I2C_RDWR, (unsigned long)&ioctl_data);
    if (ret < 0)
    {
        perror("i2c_write_data_sub ioctl error");
        free(ioctl_data.msgs[0].buf);
        free(ioctl_data.msgs);

        return -1;
    }

    return write_data_len;
}

/**
  * @name   i2c_read_data_sub
  * @brief  从有寄存器地址的i2c从设备读取数据(即读i2c从设备寄存器)
  * @param  read_data: 读取到的数据
  * @param  fd: i2c从设备文件描述符
  * @param  slave_addr: i2c从设备地址
  * @param  reg_addr: i2c从设备寄存器地址
  * @param  read_data_len: 指定读取长度
  * @retval 成功: 实际读取长度
  *         失败: -1
  */
int i2c_read_data_sub(uint8_t *read_data, const int fd, const uint8_t slave_addr,
                      const uint8_t reg_addr, const uint16_t read_data_len)
{
    int ret = -1;
    struct i2c_rdwr_ioctl_data ioctl_data = {0};

    ioctl_data.nmsgs = 2; // 消息数

    ioctl_data.msgs = (struct i2c_msg *)malloc(ioctl_data.nmsgs * sizeof(struct i2c_msg));
    if (NULL == ioctl_data.msgs)
    {
        perror("i2c_read_data_sub malloc msgs error");

        return -1;
    }

    ioctl_data.msgs[0].buf = (uint8_t *)malloc(sizeof(uint8_t));
    if (NULL == ioctl_data.msgs[0].buf)
    {
        perror("i2c_read_data_sub malloc buf[0] error");
        free(ioctl_data.msgs);

        return -1;
    }

    ioctl_data.msgs[1].buf = (uint8_t *)malloc(read_data_len * sizeof(uint8_t));
    if (NULL == ioctl_data.msgs[1].buf)
    {
        perror("i2c_read_data_sub malloc buf[1] error");
        free(ioctl_data.msgs[0].buf);
        free(ioctl_data.msgs);

        return -1;
    }

    ioctl_data.msgs[0].addr = slave_addr; // 从器件地址
    ioctl_data.msgs[0].len = 1;           // 数据长度
    ioctl_data.msgs[0].flags = 0;         // 操作方式(0: write; 1: read)
    ioctl_data.msgs[0].buf[0] = reg_addr; // 寄存器地址

    ioctl_data.msgs[1].addr = slave_addr;             // 从器件地址
    ioctl_data.msgs[1].len = read_data_len;           // 数据长度
    ioctl_data.msgs[1].flags = 1;                     // 操作方式(0: write; 1: read)
    memset(ioctl_data.msgs[1].buf, 0, read_data_len); // 初始化

    ret = ioctl(fd, I2C_RDWR, (unsigned long)&ioctl_data);
    if (ret < 0)
    {
        perror("i2c_read_data_sub read error");
        free(ioctl_data.msgs[1].buf);
        free(ioctl_data.msgs[0].buf);
        free(ioctl_data.msgs);

        return -1;
    }

    memcpy(read_data, ioctl_data.msgs[1].buf, read_data_len);

    return read_data_len;
}
